home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Communication / NewsBase / Source / TransparentWindow.m < prev    next >
Text File  |  1993-01-12  |  9KB  |  306 lines

  1. // TransparentWindow.m
  2. // By Jayson Adams, NeXT Developer Support Team
  3. // You may freely copy, distribute and reuse the code in this example.
  4. // NeXT disclaims any warranty of any kind, expressed or implied, as to its
  5. // fitness for any particular use.
  6.  
  7. // modified by Miyai, ISR    1992.7.28
  8.  
  9. #import <math.h>
  10. #import <string.h>
  11. #import <dpsclient/wraps.h>
  12. #import <appkit/publicWraps.h>
  13. #import <appkit/NXImage.h>
  14. #import <appkit/Window.h>
  15. #import <appkit/Application.h>
  16.  
  17. #import "pswraps.h"
  18. #import "AcceptWindow.h"
  19. #import "Animator.h"
  20.  
  21. #import "TransparentWindow.h"
  22. #import "errdebug.h"
  23.  
  24. #define NOWINDOW 0
  25.  
  26.  
  27. @implementation TransparentWindow
  28.  
  29.  
  30. - initForImage:anImage at:(NXPoint *)windowOrigin forView:anObject
  31. {
  32.     NXRect    windowFrame;
  33.     NXPoint    origin = {0.0, 0.0};
  34.     
  35.   /*
  36.    * create an offscreen window with the image (for use in our pswrap routines)
  37.    */
  38.     [anImage getSize:&windowSize];
  39.     windowFrame.origin.x = windowFrame.origin.y = 0.0;
  40.     windowFrame.size = windowSize;
  41.     image = [[Window alloc] initContent:&windowFrame
  42.                 style:NX_PLAINSTYLE
  43.                 backing:NX_RETAINED
  44.                 buttonMask:0
  45.                 defer:NO];
  46.  
  47.   /* copy the image to our new window */
  48.     [[image contentView] lockFocus];
  49.     [anImage composite:NX_COPY toPoint:&origin];
  50.     [[image contentView] unlockFocus];
  51.     
  52.   /* save the object that created us */
  53.     source = anObject;
  54.     
  55. //    iIconImage = [anObject image];
  56.     iIconImage = anImage;
  57.     if([anObject respondsTo:@selector(title)]) {
  58.         strncpy (iTitle, [anObject title], sizeof(iTitle)-1);
  59.     }
  60.   /*
  61.    * create an animator to move our transparent window back to its origin if
  62.    * the user lets go of the window over something that won't accept it;  we'll
  63.    * create it now so there's no delay when we really need it
  64.    */
  65.     animator = [[Animator alloc] initChronon:(1.0 / 40.0)
  66.                  adaptation:0.0
  67.                  target:self
  68.                  action:@selector(animateBack:)
  69.                  autoStart:NO
  70.                  eventMask:0];
  71.  
  72.     iDefaultAccepted = NO;
  73.  
  74.     return self;
  75. }
  76.  
  77. - free
  78. {
  79.     [image free];
  80.     [animator free];
  81.     
  82.     return [super free];
  83. }
  84.  
  85. - imageWindow
  86. {
  87.     return image;
  88. }
  89.  
  90. - image
  91. {
  92.     return iIconImage;
  93. }
  94.    
  95. - source
  96. {
  97.     return source;
  98. }
  99.    
  100. - (const char *)title
  101. {
  102.     return (const char *)iTitle;
  103. }
  104.  
  105. - dragFromMouseDown:(NXPoint *)startingPoint mouseOffset:(NXPoint *)offset
  106. {
  107.     int            mouseUp = 0, windowUnderImage, windowUnderMouseChanged = 0,
  108.             previousWindowUnderMouseChanged = 0;
  109.     unsigned int    windowNum;
  110. //    BOOL        accepted = NO;
  111.     BOOL        accepted;
  112.     float        deltaX, deltaY, distance;
  113.     
  114.     // set default for accepted
  115.     // iDefaultAccepted : NO: for IFolderTransparentWindow
  116.     //              YES: for TransparentWindow
  117.     
  118.     accepted = iDefaultAccepted;
  119.     
  120.   /* disable the wait cursor for our dragging loop */
  121.     PSsetwaitcursorenabled(NO);
  122.  
  123.   /* get the image's gstate for our dragWindow pswrap */
  124.     imageGstate = [image gState];
  125.     
  126.     currentPoint = stoppingPoint = *startingPoint;
  127.     
  128.   /* set everything up for the drag loop */
  129.     initDrag(currentPoint.x, currentPoint.y, offset->x, offset->y,
  130.              windowSize.width, windowSize.height, &iWindow, &bgWindow,
  131.          &niWindow, &igstate, &bggstate, &nigstate, &gWindow, &ggstate);
  132.  
  133.     while (!mouseUp) {
  134.       /* call the pswrap that moves the transparent window */
  135.     dragWindow(iWindow, niWindow, gWindow, windowUnderMouseChanged,
  136.                  previousWindowUnderMouseChanged, igstate, bggstate,
  137.            nigstate, imageGstate, ggstate, currentPoint.x,
  138.            currentPoint.y, offset->x, offset->y, windowSize.width,
  139.            windowSize.height, &mouseUp, &windowUnderImage,
  140.            &(currentPoint.x), &(currentPoint.y));
  141.     
  142.     [self checkForAcceptWindow:windowUnderImage
  143.           atPoint:¤tPoint
  144.                    :&windowUnderMouseChanged
  145.              :&previousWindowUnderMouseChanged];
  146.     }
  147.  
  148.   /*
  149.    * flush window's because checkForAcceptWindow might've caused windows to
  150.    * change and the user may have let go of the mouse, making mouseUp true and
  151.    * preventing dragWindow from getting called (which does the flushWindows
  152.    * normally)
  153.    */
  154.     if (windowUnderMouseChanged) {
  155.     NXConvertGlobalToWinNum(windowUnderMouseChanged, &windowNum);
  156.     [[NXApp findWindow:windowNum] flushWindow];
  157.     }
  158.  
  159.     DBG(1,fprintf(stderr,"     previousWindowUnderMouse = %d\n",
  160.                     (int)previousWindowUnderMouse));
  161.   /*
  162.    * if there was a window under the mouse point, flush it for the reasons
  163.    * above, plus tell it the user dropped the image on it
  164.    */
  165.     if (previousWindowUnderMouse) {
  166.     if (previousWindowUnderMouseChanged) {
  167.         [previousWindowUnderMouse flushWindow];
  168.     }
  169. //    accepted = [previousWindowUnderMouse windowDropped:¤tPoint
  170. //                         fromSource:source];
  171.     accepted = [previousWindowUnderMouse windowDropped:¤tPoint
  172.                          fromSource:self];
  173.     }
  174.     
  175.   /* turn the wait cursor back on */
  176.     PSsetwaitcursorenabled(YES);
  177.     
  178.   /*
  179.    * if the user didn't drop the window over an accepting window, or the
  180.    * window didn't accept it, animate the transparent window back to its origin
  181.    */
  182.     if (!accepted) {
  183.     deltaX = currentPoint.x - startingPoint->x;
  184.     deltaY = currentPoint.y - startingPoint->y;
  185.     if (deltaX && deltaY) {
  186.         distance = sqrt(deltaX  * deltaX + deltaY * deltaY);
  187.         frames = ceil(40.0 * distance / 5000.0);
  188.         if (frames == 1) {
  189.           /* make an exception for windows close to their origin */
  190.         frames = ceil(40.0 * distance / 1400.0);
  191.         }
  192.         increment.x = deltaX / frames;
  193.         increment.y = deltaY / frames;
  194.     
  195.       /* we need to remember the mouse offset */
  196.         mouseOffset = *offset;
  197.         [animator startEntry];
  198.         
  199.         [self preambleForAccepted:accepted];    //accepted = NO;
  200.         
  201.         return self;
  202.     }
  203.     }
  204.     
  205.   /* destroy the windows and gstates used to drag the TransparentWindow */
  206.     cleanup(iWindow, bgWindow, niWindow, gWindow, igstate, bggstate, nigstate,
  207.             ggstate);
  208.     
  209.     return [self free];
  210. }
  211.  
  212. - animateBack:sender
  213. {
  214.   /* compute the transparent window's new location */
  215.     currentPoint.x -= increment.x;
  216.     currentPoint.y -= increment.y;
  217.     
  218.   /* see if new location is close enough to the final position */
  219.     if ((increment.x > 0 && (currentPoint.x < stoppingPoint.x + 3.0)) ||
  220.       (increment.x < 0 && (currentPoint.x > stoppingPoint.x - 3.0))) {
  221.     currentPoint.x = stoppingPoint.x;
  222.     }
  223.     if ((increment.y > 0 && (currentPoint.y < stoppingPoint.y + 3.0)) ||
  224.       (increment.y < 0 && (currentPoint.y > stoppingPoint.y + 3.0))) {
  225.     currentPoint.y = stoppingPoint.y;
  226.     }
  227.  
  228.   /* move it there */
  229.     miniDragWindow(iWindow, niWindow, gWindow, igstate, bggstate, nigstate,
  230.                imageGstate, ggstate, currentPoint.x, currentPoint.y,
  231.            mouseOffset.x, mouseOffset.y, windowSize.width,
  232.            windowSize.height);
  233.     
  234.   /* count down the number of frames */
  235.     if (--frames) {
  236.     return self;
  237.     }
  238.     
  239.   /* all done */
  240.     [animator stopEntry];
  241.     cleanup(iWindow, bgWindow, niWindow, gWindow, igstate, bggstate, nigstate,
  242.             ggstate);
  243.     
  244.     return [self free];
  245. }
  246.  
  247. - checkForAcceptWindow:(int)windowNumUnderMouse atPoint:(NXPoint *)point
  248.   :(int *)windowUnderMouseChanged :(int *)previousWindowUnderMouseChanged
  249. {
  250.     unsigned   int    windowNum;
  251.     id            windowUnderMouse = NOWINDOW;
  252.     
  253.     *windowUnderMouseChanged = 0;
  254.     *previousWindowUnderMouseChanged = 0;
  255.       
  256.   /* find the window object under the mouse point */
  257.     if (windowNumUnderMouse) {
  258.     NXConvertGlobalToWinNum(windowNumUnderMouse, &windowNum);
  259.     windowUnderMouse = [NXApp findWindow:windowNum];
  260.     if (![windowUnderMouse
  261.                respondsTo:@selector(windowEntered:fromSource:)]) {
  262.         windowUnderMouse = NOWINDOW;
  263.         windowNumUnderMouse = 0;
  264.     }
  265.     }
  266.     
  267.   /*
  268.    * tell the window previously under the mouse (if different) that the image
  269.    * exited
  270.    */
  271.     if (windowUnderMouse != previousWindowUnderMouse &&
  272.     previousWindowUnderMouse != NOWINDOW) {
  273. //    if ([previousWindowUnderMouse windowExited:source]) {
  274.     if ([previousWindowUnderMouse windowExited:self]) {
  275.         *previousWindowUnderMouseChanged = previousWindowNumUnderMouse;
  276.     }
  277.     }
  278.     
  279.   /* tell the window under the mouse (if it exists) that the image entered */
  280.     if (windowUnderMouse != NOWINDOW) {
  281. //    if ([windowUnderMouse windowEntered:point fromSource:source]) {
  282.     if ([windowUnderMouse windowEntered:point fromSource:self]) {
  283.         *windowUnderMouseChanged = windowNumUnderMouse;
  284.     }
  285.     }
  286.     
  287.     previousWindowUnderMouse = windowUnderMouse;
  288.     previousWindowNumUnderMouse = windowNumUnderMouse;
  289.     
  290.     return self;
  291. }
  292.  
  293. - (BOOL)defaultAccepted
  294. {
  295.     return iDefaultAccepted;
  296. }
  297.  
  298. - preambleForAccepted:(BOOL)flag
  299. {
  300.     // should be overriden by its subclass
  301.     return self;
  302. }
  303.  
  304.  
  305. @end
  306.